<?php

class EASYNC_entity_generator {

    protected $c, $r, $out, $append_out, $fk_info;
    public static $EXCEPTION_PREFIX = 'EASYNC__';
    public static $ENTITY_PREFIX = 'EASYNC__';

    public function generate($host, $user, $password, $database, $file = NULL) {

        $this->c = model_conn::get_conn();

        $fk_information = new EASYNC_fk_information(model_conn::$banco);
        $this->fk_info = $fk_information->getInformation();

        $this->c = model_conn::get_conn();
        //echo "<b>entity_generator</b>" . model_conn::$banco;


        $this->r = $this->c->getDatabaseInfo();

        $this->out.= "<?php\n";
        
        $cn = new EASYNC_entity_generator_connection();
        $this->out.= $cn->get($host, $user, $password, $database);

        $this->out.= "\n\n\n\n";
        $this->classeNullColumn();

        $this->out.= "\n\n\n\n";
        $this->classeFindGeneric();

        $this->out.= "\n\n\n\n";
        $this->classeExcecao();

        $this->out.= "\n\n\n\n";
        $this->classeTableEntity();

        $this->out.= "\n\n\n\n";
        $this->classePkTableEntity();

        $this->out.= "\n\n\n\n";
        $this->classeCollectionGeneric();


        foreach ($this->r as $tables) {
            foreach ($tables as $table => $columns) {


                // verificando se esta tabela possui chave prim�ria:
                $have_pk = false;

                // $column_info[0] = is PK; 
                // $column_info[1] = NOT NULL;
                foreach ($columns as $column => $column_info) {
                    if ($column_info[0] == 1) {
                        $have_pk = true;
                        break;
                    }
                }

                if ($have_pk) {
                    $this->withPK($table, $columns);
                    $this->classeFind($table, $columns);
                    $this->out.= "\n\n\n\n";
                } else {
                    $this->withoutPK($table, $columns);
                }
                $this->out.= "\n\n\n\n";
                $this->classeCollection($table);
                $this->out.= "\n\n\n\n";
            }
        }
        $this->out.= $this->append_out;
        
        $this->out.= "\n?>";

        if($file === NULL) {
            return $this->out;
        }
        
        $fp = fopen($file, 'w+');
        fwrite($fp, $this->out);
        fclose($fp);
    }

    /**
     *
     * @return bool
     */
    protected function columnCanBeNull($table_arg, $column_arg) {
        foreach ($this->r as $tables) {
            foreach ($tables as $table => $columns) {
                if ($table == $table_arg) {

                    // $column_info[0] = is PK; 
                    // $column_info[1] = NOT NULL;
                    foreach ($columns as $column => $column_info) {
                        if ($column == $column_arg) {
                            if ($column_info[1] == 1) {
                                //echo "$table_arg:$column_arg = CANNOT BE NULL";
                                return false;
                            }
                            //echo "$table_arg:$column_arg = CAN BE NULL";
                            return true;
                        }
                    }
                }
            }
        }
    }

    
    protected function withPK($table, $columns) {


        $this->out.= "class " . self::$ENTITY_PREFIX . "$table extends pk_table_entity {
        
        public static \$table = '$table';
        
        // NOME DAS COLUNAS DISPONÍVEIS:
        ";

        foreach ($columns as $column => $column_info) {
            $this->out.= "public static \$COLUMN_" . $column . " = '$column';
                    ";
        }




        $this->out.= "
        // COLUNAS ALIMENTADAS DO BANCO?
                
                ";

        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 0) {
                $this->out.= "protected \$feeded_$column = false;
                    ";
            }
        }



        $this->out.= "
        // CAMPOS:
                
                ";

        foreach ($columns as $column => $column_info) {
            $this->out.= "protected $$column = NULL;
                    ";
        }




        $this->out.= "
        // CHAVES prim�rias com novos valores:
                
                ";

        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                $this->out.= "protected \$new_$column = NULL;
                    ";
            }
        }




        $this->out.= "
            
public function __construct(";


        $first = true;
        foreach ($columns as $column => $column_info) {

            if ($column_info[0] == 0) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= ", ";
                }
                $this->out.= "$$column = NULL";
            }
        }




        $this->out.= ") {

";

        foreach ($columns as $column => $column_info) {

            if ($column_info[0] == 0) {
                $this->out.= "\$this->set" . ucfirst($column) . "($$column);\n";
            }
        }



        $this->out.= "
}


";





        // REFERÊNCIAS A CHAVE ESTRANGEIRA:


        if (!empty($this->fk_info)) {

            foreach ($this->fk_info as $t => $columns_fk) {
                if ($t == $table) {
                    
                    foreach ($columns_fk as $info) {
                        
                        $column_name = '';
                        $ref_table = '';

                        foreach ($info as $type => $name) {

                            if ($type == 'COLUMN_NAME') {
                                $column_name = $name;
                            }

                            if ($type == 'REFERENCED_TABLE_NAME') {
                                $ref_table = $name;
                            }
                        }
                        
                        $column_can_be_null = $this->columnCanBeNull($table, $column_name);
                        
                        
                        $this->out.= "
                            /**";
                        
                        if($column_can_be_null) {
                            $this->out.= "* @return " . self::$ENTITY_PREFIX . "_NullColumn_$ref_table";
                            
                        }else{
                            $this->out.= "* @return " . self::$ENTITY_PREFIX . "$ref_table";
                        }
                        

$this->out.= "*/
public function get_REFERENCE_" . ucfirst($ref_table) . "__USING_COLUMN__" . ucfirst($column_name) . "() {";


                        if ($column_can_be_null) {
                            $this->out.="
\$has_value = (\$this->$column_name === NULL) ? false : true;
return new " . self::$ENTITY_PREFIX . "_NullColumn_" . ucfirst($table) . "__USING_COLUMN__" . ucfirst($column_name) . "(\$has_value, \$this->$column_name);


";
                        } else {
                            $this->out.="
return " . self::$ENTITY_PREFIX . "$ref_table::getByPk(\$this->$column_name);";
                        }
                        
                        $this->out.= "} // end get_REFERENCE_()";
                        
                        
                        // criando a classe NullColumn Específica da tabela:
                        if($column_can_be_null) {
                            $this->append_out.= "
class " . self::$ENTITY_PREFIX . "_NullColumn_" . ucfirst($table) . "__USING_COLUMN__" . ucfirst($column_name) . " extends " . self::$ENTITY_PREFIX . "_NullColumn_GENERIC { 

/**
     *
     * @return " . self::$ENTITY_PREFIX . "$ref_table
     */
    public function value() {
        return \$this->value;
    }

}";
                        }
                        
                    }
                    break;
                }
            }
        }





        // GET OBJECT

        $this->out.= "
    /**
     *
     * @return " . self::$ENTITY_PREFIX . "$table
     */
    public static function getObject(\$object) {
        return \$object;
    }
    

";













        // GET BY PK

        $this->out.= "
            /**
             * 
             * @return " . self::$ENTITY_PREFIX . "$table} 
             * @throws " . self::$EXCEPTION_PREFIX . "ObjectNotFoundException
             */
        public static function getByPK(";


        $first = true;
        foreach ($columns as $column => $column_info) {



            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= ", ";
                }
                $this->out.= "$$column";
            }
        }


        $this->out.= ") {\n";

        $this->out.= "\$table = new " . self::$ENTITY_PREFIX . "$table();";


        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                $this->out.= "\$table->set" . ucfirst($column) . "($$column);
                        ";
            }
        }




        $this->out.= "
        // verificando se a chave prim�ria existe:
        \$r = model_conn::get_conn()->qcv(\"SELECT COUNT(*) AS total FROM $table WHERE ";



        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= " AND ";
                }
                $this->out.= "$column = '$$column'";
            }
        }




        $this->out.= "\", \"total\");
            if(\$r[0] == 0) {
                // não existe.
                throw new " . self::$EXCEPTION_PREFIX . "ObjectNotFoundException();
            }";




        // alimentando os atributos:
        $this->out.= "\$table->feedFromDB();
            
return \$table; }";

        // FIM GET BY PK
        // 
        // SET

        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                $this->out.= "
                        
    public function set" . ucfirst($column) . "($$column) {
        \$this->$column = $$column;
        if (\$this->new_$column === NULL) {
            \$this->new_$column = $$column;
        }
    }
                        
                        
                        
    public function set_NEW_" . ucfirst($column) . "(\$new_$column) {
        \$this->new_$column = \$new_$column;
    }
                        
                    ";
            } else {
                $this->out.= "
                        
    public function set" . ucfirst($column) . "($$column) {
        \$this->$column = $$column;
    }";
            }
        }





        // GET

        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                // CHAVE PRIM�RIA:

                $this->out.= "
public function get" . ucfirst($column) . "() {
        return \$this->$column;
    }                    

";
            } else {
                // N�O � CHAVE PRIM�RIA:


                if ($column_info[1] == 1) {
                    // NOT NULL:

                    $this->out.= "
                    

public function get" . ucfirst($column) . "() {
        if (!\$this->feeded_$column) {
            \$r = \$this->con()->qcv(\"
                        SELECT $column 
                        FROM $table
                        WHERE ";

                    $first = true;
                    foreach ($columns as $column2 => $column_info2) {
                        if ($column_info2[0] == 1) {
                            if ($first) {
                                $first = false;
                            } else {
                                $this->out.= " AND ";
                            }
                            $this->out.= "$column2 = '\" . \$this->$column2 . \"'";
                        }
                    }


                    $this->out.= "
                            \", \"$column\");
            \$this->$column = \$r[0];
            \$this->feeded_$column = true;
        }
        return \$this->$column;
    }
                        

";
                } else {
                    // CAN BE NULL:

                    $this->out.= "
                    

public function get" . ucfirst($column) . "() {
        if (!\$this->feeded_$column) {
            \$r = \$this->con()->qcv(\"
                        SELECT $column, ISNULL($column) isnull
                        FROM $table
                        WHERE ";

                    $first = true;
                    foreach ($columns as $column2 => $column_info2) {
                        if ($column_info2[0] == 1) {
                            if ($first) {
                                $first = false;
                            } else {
                                $this->out.= " AND ";
                            }
                            $this->out.= "$column2 = '\" . \$this->$column2 . \"'";
                        }
                    }


                    $this->out.= "
                            \", \"$column,isnull\");
                       
            \$this->$column = NULL;
            if (\$r[0][1] == '0') {
                \$this->$column = \$r[0][0];
            }
            \$this->feeded_$column = true;
        }
        \$has_value = (\$this->$column === NULL) ? false : true;
        return new " . self::$ENTITY_PREFIX . "_NullColumn__TABLE_" . ucfirst($table) . "__COLUMN_" . ucfirst($column) . "(\$has_value, \$this->$column);
    }
                        

";
                    
                    
                            $this->append_out.= "
class " . self::$ENTITY_PREFIX . "_NullColumn__TABLE_" . ucfirst($table) . "__COLUMN_" . ucfirst($column) . " extends " . self::$ENTITY_PREFIX . "_NullColumn_GENERIC { 

/**
     *
     * @return " . self::$ENTITY_PREFIX . "$table
     */
    public function value() {
        return \$this->value;
    }

}";
                    
                }
            }
        }



        $this->out.= "public function feedFromDB() {";
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 0) {
                $this->out.= "\$this->get" . ucfirst($column) . "();\n";
            }
        }
        $this->out.= "}";





        $this->out.= "
public function save() {


if(
        ";


        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= " || ";
                }
                $this->out.= "\$this->$column === NULL";
            }
        }


        $this->out.="
                
) {
            \$this->save_insert();
        }else{
            // verificando se a chave prim�ria existe:
            \$r = \$this->con()->qcv(\"SELECT COUNT(*) AS total FROM $table WHERE ";



        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= " AND ";
                }
                $this->out.= "$column = '\$this->$column'";
            }
        }




        $this->out.= "\", \"total\");
            if(\$r[0] == 0) {
                // n�o existe.
                \$this->save_insert();
            }else{
                // registro j� existe.
                \$this->save_update();
            }
            \$this->save_update();
        }
    }            
";








        // SAVE UPDATE


        $this->out.= "
    /**
     * @throws DBException
     */
    protected function save_update() {

                ";


        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 0) {
                $this->out.= "$$column = (\$this->$column === NULL) ? \"NULL\" : \"'\" . addslashes(\$this->$column) . \"'\";";
            }
        }

        $this->out.= "
            \$q = \"
            UPDATE $table 
            SET ";

        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= ", ";
            }
            if ($column_info[0] == 1) {

                $this->out.= "$column = \$this->new_$column";
            } else {
                $this->out.= "$column = \$$column";
            }
        }


        $this->out.= " WHERE ";

        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= " AND ";
                }
                $this->out.= "$column = '\$this->$column'";
            }
        }
        $this->out.= "\";
            \$this->con()->q(\$q);
} // CLOSE save_update()
";






        // SAVE INSERT

        $this->out.= "
                    
protected function save_insert() {";

        foreach ($columns as $column => $column_info) {
            $this->out.= "$$column = (\$this->$column === NULL) ? \"NULL\" : \"'\" . addslashes(\$this->$column) . \"'\";";
        }


        $this->out.="        
                    
                    \$q = \"
INSERT INTO $table (";


        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= ", ";
            }
            $this->out.= "$column";
        }



        $this->out.=") VALUES (";



        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= ", ";
            }
            $this->out.= "$$column";
        }





        $this->out.= ");\";            

\$this->con()->q(\$q);

} // CLOSE SAVE_INSERT";





        $this->out.= "
                
  public function remove() {
        
        \$q = \"
            DELETE FROM $table 
            WHERE ";


        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= " AND ";
                }
                $this->out.= "$column = '\$this->$column'";
            }
        }


        $this->out.= "\";
        
        \$this->con()->q(\$q);
        
    } // close remover()
    


} // close classe;

";
    }

    protected function withoutPK($table, $columns) {
        $this->out.= "class " . self::$ENTITY_PREFIX . "$table extends table_entity {
        
        public static \$table = '$table';
        
        // NOME DAS COLUNAS DISPONÍVEIS:
        ";

        foreach ($columns as $column => $column_info) {
            $this->out.= "public static \$COLUMN_" . $column . " = '$column';
                    ";
        }



        $this->out.= "
        // CAMPOS:
                
                ";

        foreach ($columns as $column => $column_info) {
            $this->out.= "protected $$column = NULL;
                    ";
        }




        $this->out.= "
        // NOVOS VALORES:
                
                ";

        foreach ($columns as $column => $column_info) {
            $this->out.= "protected \$new_$column = NULL;
                    ";
        }




        $this->out.= "
        // NOVOS VALORES ALIMENTADOS?
                
                ";

        foreach ($columns as $column => $column_info) {
            $this->out.= "protected \$feeded_new_$column = FALSE;
                    ";
        }




        $this->out.= "
            


    /**
     *
     * @return " . self::$ENTITY_PREFIX . "$table
     */
    public static function getObject(\$object) {
        return \$object;
    }
    

";









        // REFERÊNCIAS A CHAVE ESTRANGEIRA:


        if (!empty($this->fk_info)) {

            foreach ($this->fk_info as $t => $columns_fk) {
                if ($t == $table) {
                    foreach ($columns_fk as $info) {

                        $column_name = '';
                        $ref_table = '';

                        foreach ($info as $type => $name) {

                            if ($type == 'COLUMN_NAME') {
                                $column_name = $name;
                            }

                            if ($type == 'REFERENCED_TABLE_NAME') {
                                $ref_table = $name;
                            }
                        }
                        $this->out.= "
                            /**
* @return " . self::$ENTITY_PREFIX . "$ref_table
*
*/

                                    public function get_REFERENCE_" . ucfirst($ref_table) . "__USING_COLUMN__" . ucfirst($column_name) . "() {

return " . self::$ENTITY_PREFIX . "$ref_table::getByPk(\$this->$column_name);


}";
                    }
                }
            }
        }











        // SET

        foreach ($columns as $column => $column_info) {

            $this->out.= "
                        
    public function set" . ucfirst($column) . "($$column) {
        \$this->$column = $$column;
                    if(!\$this->feeded_new_$column) {
                        // só modifica esta variável se não estiver alimentada.
                        \$this->new_$column = $$column;
                    }
    }";
        }



        // SET NEW

        foreach ($columns as $column => $column_info) {

            $this->out.= "
                        
    public function set_NEW_" . ucfirst($column) . "($$column) {
        \$this->new_$column = $$column;
        \$this->feeded_new_$column =  TRUE;
    }";
        }





        // GET

        foreach ($columns as $column => $column_info) {

            $this->out.= "
                    
public function get" . ucfirst($column) . "() {
        // retorna o valor que setou, pois não é possível recuperar do banco uma coluna sem chave primária
        return \$this->$column;
} // fim get()
                        

";
        }








        // SAVE UPDATE


        $this->out.= "
    /**
     * @throws DBException
     * \$limit_to_update: quantos registros atualizar (útil pois podem ter mais de 1 registro com o mesmo valor nas colunas). Deixar NULL para não ter limite, ou ajustar o número de limite.
     */
    public function update(\$limit_to_update = NULL) {


                ";


        // atual:
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 0) {
                $this->out.= "$$column = (\$this->$column === NULL) ? \"NULL\" : \"'\" . addslashes(\$this->$column) . \"'\";";
            }
        }


        // novo:
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 0) {
                $this->out.= "\$new_$column = (\$this->new_$column === NULL) ? \"NULL\" : \"'\$this->new_$column'\";";
            }
        }


        $this->out.= "
            \$q = \"
            UPDATE $table 
            SET ";

        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= ",";
            }
            $this->out.= "$column = '\$this->new_$column'";
        }


        $this->out.= " WHERE ";

        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= " AND ";
            }
            $this->out.= "$column = '\$this->$column'";
        }


        $this->out.= "\";
            
if(\$limit_to_update !== NULL) {
    \$q.= \" LIMIT \$limit_to_update\";
}


";


        $this->out.= "
            \$this->con()->q(\$q);
} // CLOSE save_update()
";






        // INSERT

        $this->out.= "
                    
public function insert() {";

        foreach ($columns as $column => $column_info) {
            $this->out.= "$$column = (\$this->$column === NULL) ? \"NULL\" : \"'\" . addslashes(\$this->$column) . \"'\";";
        }


        $this->out.="        
                    
                    \$q = \"
INSERT INTO $table (";


        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= ", ";
            }
            $this->out.= "$column";
        }



        $this->out.=") VALUES (";



        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= ", ";
            }
            $this->out.= "$$column";
        }




        $this->out.= "
);\";            

} // CLOSE INSERT";





        $this->out.= "
                
  public function remove() {
        
        \$q = \"
            DELETE FROM $table 
            WHERE ";


        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($first) {
                $first = false;
            } else {
                $this->out.= " AND ";
            }
            $this->out.= "$column = '\$this->$column'";
        }


        $this->out.= "\";
        
        \$this->con()->q(\$q);
        
    } // close remover()
    


} // close classe;

";
    }

    protected function classeCollectionGeneric() {
        $this->out.= "
                
                class " . self::$ENTITY_PREFIX . "_COLLECTION__GENERIC {
                
protected \$collection = array();


public function getAmount() {
        return sizeof(\$this->collection);
    }
    

     public function getCollectionAsArray() {
        return \$this->collection;
    }

}

";
    }

    protected function classeCollection($table) {
        $this->out.= "
                
                
                
                class " . self::$ENTITY_PREFIX . "_COLLECTION__{$table} extends " . self::$ENTITY_PREFIX . "_COLLECTION__GENERIC {
        
                
    /**
     *
     * @param " . self::$ENTITY_PREFIX . "$table $table 
     */
    public function add" . ucfirst($table) . "($$table) {
        array_push(\$this->collection, $$table);
    }
    
    
    /**
     *
     * @param int \$index
     * @return " . self::$ENTITY_PREFIX . "$table 
     */
    public function getByIndex(\$index) {
        return \$this->collection[\$index];
    }
              
                
        }
        
        
        ";
    }

    protected function classeFind($table, $columns) {


        $this->out.= "
            
class " . self::$ENTITY_PREFIX . "_FIND__$table extends " . self::$ENTITY_PREFIX . "_FIND__GENERIC {

    public function selectAll() {
                if(!\$this->select_all_called) {
        \$this->query = \"SELECT ";




        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= ", ";
                }
                $this->out.= "$column";
            }
        }




        $this->out.= "
        FROM $table\";
                \$this->select_all_called = true;
                }
    } // close selectAll();

                ";



        foreach ($columns as $column => $column_info) {

            $this->out.= "
/**
* @throws " . self::$EXCEPTION_PREFIX . "FindCallOrderException
*/
public function filterBy" . ucfirst($column) . "($$column) {
                    
                    
                    if(\$this->order_by_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"You must call 'filterBy...' functions before 'orderBy' function.\");
    }
    if(\$this->limit_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"You must call 'filterBy...' functions before 'limit...' functions.\");
    }
                    
                    
                    
                        \$this->selectAll();
                        
                        
                        \$valor = \"NULL\";
        if ($$column !== NULL) {
            \$$column = addslashes($$column);
            \$valor = \"'$$column'\";
        }

        \$this->addWhereOrAnd();
        \$this->addQuery(\"$column = \$valor\");
                        
                        
                        
                        
                       } // close filterBy ";
        }






        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 0) {
                $this->out.= "
/**
* @throws " . self::$EXCEPTION_PREFIX . "FindCallOrderException
*/
public function filterBy_LIKE_" . ucfirst($column) . "($$column) {
                        
                        
                         if(\$this->order_by_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"You must call 'filterBy...' functions before 'orderBy' function.\");
    }
    if(\$this->limit_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"You must call 'filterBy...' functions before 'limit...' functions.\");
    }
                        
                        \$this->selectAll();
                        
                        \$valor = \"NULL\";
        if ($$column !== NULL) {
            \$$column = addslashes($$column);
            \$valor = \"'$$column'\";
        }

        \$this->addWhereOrAnd();
        \$this->addQuery(\"$column LIKE \$valor\");
                        
                        
                        
                        
                       } // close filterBy ";
            }
        }




        $this->out.= "


    /**
     *
     * @return " . self::$ENTITY_PREFIX . "_COLLECTION__$table
     * @throws MARCEL_ORM_ObjectNotFoundException caso n�o encontre nenhum resultado.
     */
    public function get() {
        
                \$this->selectAll();
                
        \$this->con = model_conn::get_conn();
        \$this->addQuery(\";\");
        \$collection = new " . self::$ENTITY_PREFIX . "_COLLECTION__$table();
        
        \$r = \$this->con->qcv(\$this->query, \"";


        $qtde_chaves_primarias = 0;
        $first = true;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= ",";
                }
                $this->out.= "$column";
                $qtde_chaves_primarias++;
            }
        }






        $this->out.= "\");
        
        if(\$this->con->getQueryRows() != 0) {
            
        

            foreach (\$r as \$v) {
                \$object = " . self::$ENTITY_PREFIX . "$table::getByPk(";



        $first = true;
        $index = 0;
        foreach ($columns as $column => $column_info) {
            if ($column_info[0] == 1) {
                if ($first) {
                    $first = false;
                } else {
                    $this->out.= ", ";
                }
                if ($qtde_chaves_primarias > 1) {
                    $this->out.= "\$v[$index]";
                } else {
                    $this->out.= "\$v";
                }
                $index++;
            }
        }





        $this->out.= ");
                \$collection->add" . ucfirst($table) . "(\$object);
                \$this->amount_found++;
                
            } // fim foreach
        
        } // fim if
    
        return \$collection;
    } // end get()
    
} // end class

";
    }

    protected function classeFindGeneric() {
        $this->out.= "
            


/**
 * " . self::$ENTITY_PREFIX . "_FIND__GENERIC
 * 
 * ordem de consulta:
 * 
 * \$e = new " . self::$ENTITY_PREFIX . "_FIND__usuario();
 * \$e->selectAll();
 * \$e->filterByNome('marcel');
 * \$e->filterBySenha('123');
 * 
 * retorna um tipo " . self::$ENTITY_PREFIX . "_COLLECTION__usuario:
 * \$resultado = \$e->get();
 * 
 */
abstract class " . self::$ENTITY_PREFIX . "_FIND__GENERIC {
    protected \$query = \"\";
    protected \$whereAdded = false;
    protected \$amount_found = 0;
    protected \$con;
    
    protected \$select_all_called = false;
    protected \$order_by_called = false;
    protected \$limit_called = false;

    public abstract function selectAll();

    protected function addWhereOrAnd() {
        if (\$this->whereAdded) {
            \$this->addQuery(\" AND \");
        }else{
           \$this->addQuery(\" WHERE \");
            \$this->whereAdded = true;
        }
    }

    protected function addQuery(\$query) {
        \$this->selectAll();
        \$this->query.= \$query;
    }


/**
* @throws " . self::$EXCEPTION_PREFIX . "FindCallOrderException
*/
    public function orderBy(\$column) {
        if(\$this->limit_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"You must call 'orderBy' function before 'limit' function.\");
        }
        \$column = addslashes(\$column);
        \$this->addQuery(\" ORDER BY \" . \$column);
        \$this->order_by_called = true;
    }
    
    public function limitAmount(\$amount) {
        if(\$this->limit_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"The 'limit' function has already called.\");
        }
        \$this->addQuery(\" LIMIT \$amount\");
        \$this->limit_called = true;
    }
    
    public function limitStartAmount(\$start, \$amount) {
        if(\$this->limit_called) {
            throw new " . self::$EXCEPTION_PREFIX . "FindCallOrderException(\"The 'limit' function has already called.\");
        }
        \$this->addQuery(\" LIMIT \$start, \$amount\");
        \$this->limit_called = true;
    }

    
    
    
    /**
     *
     * @return int quantidade de registros encontrados com a consulta.
     */
    public function amountFound() {
       return \$this->amount_found;
    }
}


";
    }

    protected function classeExcecao() {

        $this->out.= "
            


// objeto não encontrado (getByPk):
class " . self::$EXCEPTION_PREFIX . "ObjectNotFoundException extends Exception { }

// falha ao salvar objeto no banco (salvar):
class " . self::$EXCEPTION_PREFIX . "SaveException extends Exception { }

// não encontrou registro algum na tabela (getAll):
class " . self::$EXCEPTION_PREFIX . "EmptyTableException extends Exception { }

// não pode remover registro porque � chave estrangeira em outra tabela (remover):
class " . self::$EXCEPTION_PREFIX . "ForeignKeyConstraintException extends Exception { }
    
// ordem de chamada de funções da classe FIND incorreta.
class " . self::$EXCEPTION_PREFIX . "FindCallOrderException extends Exception { }



";
    }

    protected function classeNullColumn() {
        $this->out.= "
            
class " . self::$ENTITY_PREFIX . "_NullColumn_GENERIC {

    protected \$has_value;
    protected \$value;

    public function __construct(\$has_value, \$value = NULL) {

        \$this->has_value = \$has_value;
        \$this->value = \$value;
    }

    public function hasValue() {
        return \$this->has_value;
    }

    public function value() {
        return \$this->value;
    }

}

";
    }

    protected function classeTableEntity() {
        $this->out.= "
class table_entity {

    protected \$con = null;
    protected static \$table;

    
    /**
     *
     * @return modelo_dbm_orm
     */
    protected function con() {
        \$this->con = model_conn::get_conn();
        return \$this->con;
    }
}            
";
    }

    protected function classePkTableEntity() {
        $this->out.= "
abstract class pk_table_entity extends table_entity {
    public abstract function feedFromDB();
}
";
    }

}

?>